package puppy.demo.tagRanking;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

import util.nlp.Constants;
import util.nlp.LM;

public class RankJob implements Runnable {

	/**
	 * @param args
	 */

	private LM model = null;
	private HashSet<String> tags = null;
	private String candidate = null;
	private CyclicBarrier barrier = null;

	private boolean userWeight = true;

	private Hashtable<String, Hashtable<String, Double>> graph_distances = null;

	private Hashtable<String, Double> scores = null;

	public RankJob(LM model, HashSet<String> tags, String candidate,
			Hashtable<String, Double> scores, CyclicBarrier barrier,
			boolean userWeight) {

		this.model = model;

		this.graph_distances = model.getGraphModel();
		this.tags = tags;
		this.candidate = candidate;
		this.barrier = barrier;
		this.scores = scores;
		this.userWeight = userWeight;
	}

	@Override
	public void run() {

		// calculate score

		calculateScore();

		try {

			barrier.await();
		} catch (InterruptedException ex) {
			ex.printStackTrace();
		} catch (BrokenBarrierException ex) {
			ex.printStackTrace();
		}

		// TODO Auto-generated method stub

	}

	public void calculateScore() {
		Iterator<String> iterator = tags.iterator();

		double prob = 1;
		double uni_prob = 0;
		// System.out.println(graph_distances.size()-i);

		Hashtable<String, Double> hash = graph_distances.get(candidate);

		/*
		 * TODO : Enhance more evidence tags hits
		 */

		// System.out.println(candidate + "\t"+
		// model.getUserWeight1(candidate));

		while (iterator.hasNext()) {

			String t = iterator.next();

			uni_prob = 0;
			if (graph_distances.containsKey(t)) {

				uni_prob = graph_distances.get(t).get(t);
			}

			double temp = 0.0d;
			if (hash.containsKey(t)) {

				temp = hash.get(t);

			}

			double weight = 0;

			// dirichlet smoothing
			// double Uu = userWeight + model.getUsersFreqKids().get(t);
			// userWeight = userWeight + Constants.u1*

			// linear interpolation
			prob = prob
					* (temp * Constants.ALPHA + uni_prob * Constants.BETHA + Constants.CETHA);

			if (userWeight && model.userWeights.containsKey(t)) {
				weight = model.userWeights.get(t);
				
			}
			weight = weight + Constants.CETHA;
			// linear interpolation

			if (userWeight) {
			
				prob = prob * weight;
			}

			// System.out.println(temp + "\t"+ uni_prob+"\t" +1+"\t"+ userWeight
			// );

			// double diri =
			// temp*model.getTotal_items_global()/(double)(model.getTotal_items_global()+
			// Constants.u)+
			// (double)uni_prob*Constants.u/(double)(model.getTotal_items_global()+
			// Constants.u);

			// if(diri!=0.0d)
			// prob = prob * diri;

			// dirichtlet smoothing

			// if(temp!=0)
			// System.out.println("Bigram:" + temp);
			// System.out.println("Unigram: " + uni_prob );
			// prob = (prob*temp*model.getTotal_unigrams() + uni_prob
			// *Constants.u)/(double)((double)model.getTotal_unigrams()+
			// Constants.u);

		}

		/**
		 * In this part can be introduced a different s probability (considering
		 * the global counts - non kids)
		 * 
		 * 
		 */

		/*
		 * Now we multiply by the prior probability of s p(s|k)
		 */

		double s = (double) model.getUni(candidate);
		prob = prob * s;

		/**
		 * 
		 * In this part we introduce the user weight for the candidate tag
		 * (experiment with this)
		 * 
		 */

		if (userWeight) {
			double userWeightCandidate = model.getUserWeight(candidate);
			// System.out.println("user weight: \t" + candidate +"\t"+
			// userWeightCandidate);
			prob = prob * userWeightCandidate;

		}

		// tag kids - adults differentiattion penalize highly frequent tags
		// in adults

		// double
		// penalize_prob=model.getGlobalUni(candidate)-model.getUni(candidate)*model.getTotal_unigrams();

		// penalize_prob = penalize_prob /1000000d;
		// prob = prob/penalize_prob;
		// System.out.println(penalize_prob + "\t"+ candidate);

		if (candidate.equals(util.delicious.Constants.UNI_TOTAL_TAG)) {
			scores.put(candidate, new Double(0));
		} else {
			scores.put(candidate, prob);

		}

		// System.out.println("Adding score for " + candidate + "\t"+ s + "\t" +
		// model.getUni(candidate) + "\t" + model.getTotal_unigrams());
	}

}
